
package cz.muni.fi.pa165.carpark.servicies;

import cz.muni.fi.pa165.carpark.TO.ServiceCheckTO;
import cz.muni.fi.pa165.carpark.TO.VehicleTO;
import cz.muni.fi.pa165.carpark.VehicleStatus;
import cz.muni.fi.pa165.carpark.dao.ServiceCheckDAO;
import cz.muni.fi.pa165.carpark.dao.VehicleDAO;
import cz.muni.fi.pa165.carpark.entities.ServiceCheck;
import cz.muni.fi.pa165.carpark.entities.Vehicle;
import java.util.LinkedList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.convert.ConversionService;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 *
 * @author xborza
 */
@Service
public class ServiceCheckServiceImpl implements ServiceCheckService{
    
    @Autowired
    private ServiceCheckDAO serviceCheckDAO;
    
    @Autowired
    private VehicleDAO vehicleDAO;
    
    @Autowired
    @Qualifier("TOconverter")
    private ConversionService convertor;

    @PreAuthorize("hasRole('vehicle_manager') or hasRole('superadmin')")
    @Override
    @Transactional
    public void createCheck(ServiceCheckTO serviceCheck) {
        ServiceCheck sc = convertor.convert(serviceCheck, ServiceCheck.class);
        serviceCheckDAO.createCheck(sc);
        serviceCheck.setId(sc.getId());        
    }

    @PreAuthorize("hasRole('vehicle_manager') or hasRole('superadmin')")
    @Override
    @Transactional
    public ServiceCheckTO retrieveCheck(Long id) {
        ServiceCheck sc = serviceCheckDAO.retrieveCheck(id);
        ServiceCheckTO scto = convertor.convert(sc, ServiceCheckTO.class);
        return scto;
    }

    @PreAuthorize("hasRole('vehicle_manager') or hasRole('superadmin')")
    @Override
    @Transactional
    public void updateCheck(ServiceCheckTO serviceCheck) {
        ServiceCheck sc = convertor.convert(serviceCheck, ServiceCheck.class);
        Vehicle vehicle = serviceCheckDAO.findServiceCheckVehicle(sc);
        boolean active = false;
        if(vehicle != null && !sc.isCheckDone() && ( sc.getLastCheck() + sc.getCheckInterval() < vehicle.getNumberOfKms())){
            vehicle.setStatus(VehicleStatus.MAINTENANCE_REQUIRED);
            active = true;
            vehicleDAO.update(vehicle);
        }
        if(sc != null){
            sc.setIsActive(active);
        }
        serviceCheckDAO.updateCheck(sc);
    }

    @PreAuthorize("hasRole('vehicle_manager') or hasRole('superadmin')")
    @Override
    @Transactional
    public void deleteCheck(ServiceCheckTO serviceCheck) {
        ServiceCheck sc = convertor.convert(serviceCheck, ServiceCheck.class);
        Vehicle vehicle = serviceCheckDAO.findServiceCheckVehicle(sc);
        if(vehicle != null){
            if(vehicleDAO.getActiveServiceChecks(vehicle,true).size() == 1 && sc.isIsActive()){
                vehicle.setStatus(VehicleStatus.AVAILABLE);
            }
            vehicle.disconnectServiceCheck(sc);
            vehicleDAO.update(vehicle);
        }
        serviceCheckDAO.deleteCheck(sc);
    }
    
    @PreAuthorize("hasRole('vehicle_manager') or hasRole('superadmin')")
    @Override
    @Transactional
    public void cancelCheck(ServiceCheckTO serviceCheck){
        ServiceCheck sc = convertor.convert(serviceCheck, ServiceCheck.class);
        Vehicle vehicle = serviceCheckDAO.findServiceCheckVehicle(sc);

        sc.setIsActive(false);
        sc.setCheckDone(true);
        sc.setLastCheck(vehicle.getNumberOfKms());
        serviceCheckDAO.updateCheck(sc);
        // Create new serviceCheck
        ServiceCheck repeated = new ServiceCheck();
        repeated.setCheckInterval(sc.getCheckInterval());
        repeated.setLastCheck(sc.getLastCheck());
        repeated.setCheckPurpose(sc.getCheckPurpose());
        serviceCheckDAO.createCheck(repeated);
        // bind serviceCheck with vehicle
        vehicle.addControlServiceCheck(repeated);
         //check active ServiceChecks in Vehicle set
        if(vehicleDAO.getActiveServiceChecks(vehicle,true).isEmpty()){
            vehicle.setStatus(VehicleStatus.AVAILABLE);
        }

        vehicleDAO.update(vehicle);
    }

    @PreAuthorize("hasRole('vehicle_manager') or hasRole('superadmin')")
    @Override
    @Transactional
    public List<ServiceCheckTO> retrieveAllServiceChecks() {
        List<ServiceCheck> checks =  serviceCheckDAO.findAllServiceChecks();
        List<ServiceCheckTO> checkTOs = new LinkedList<ServiceCheckTO>();
        for(ServiceCheck s : checks)
        {
            checkTOs.add(convertor.convert(s, ServiceCheckTO.class));
        }            
        return checkTOs;
    }
  
    @PreAuthorize("hasRole('vehicle_manager') or hasRole('superadmin')")
    @Override
    public VehicleTO findServiceCheckVehicle(ServiceCheckTO check){
        ServiceCheck chck = convertor.convert(check, ServiceCheck.class);
        Vehicle vehicle = serviceCheckDAO.findServiceCheckVehicle(chck);
        return convertor.convert(vehicle, VehicleTO.class);
    }

    public void setServiceCheckDAO(ServiceCheckDAO serviceCheckDAO) {
        this.serviceCheckDAO = serviceCheckDAO;
    }  

    public VehicleDAO getVehicleDAO() {
        return vehicleDAO;
    }

    public void setVehicleDAO(VehicleDAO vehicleDAO) {
        this.vehicleDAO = vehicleDAO;
    }
    
    @PreAuthorize("hasRole('vehicle_manager') or hasRole('superadmin')")
    @Override
    public List<ServiceCheckTO> getServiceChecksByActive(boolean active) {
        List<ServiceCheck> checks =  serviceCheckDAO.getServiceChecksByActive(active);
        List<ServiceCheckTO> checkTOs = new LinkedList<ServiceCheckTO>();
        for(ServiceCheck s : checks)
        {
            checkTOs.add(convertor.convert(s, ServiceCheckTO.class));
        }            
        return checkTOs;
    }

    @PreAuthorize("hasRole('vehicle_manager') or hasRole('superadmin')")
    @Override
    public List<ServiceCheckTO> getServiceChecksByDone(boolean done) {
        List<ServiceCheck> checks =  serviceCheckDAO.getServiceChecksByDone(done);
        List<ServiceCheckTO> checkTOs = new LinkedList<ServiceCheckTO>();
        for(ServiceCheck s : checks)
        {
            checkTOs.add(convertor.convert(s, ServiceCheckTO.class));
        }            
        return checkTOs;
    }

}
